home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Math / RPN.php < prev    next >
PHP Script  |  2004-10-01  |  29KB  |  1,003 lines

  1. <?php
  2.  
  3. /**
  4.  * Math::Rpn
  5.  *
  6.  * Purpose:
  7.  *
  8.  *     Change Expression To RPN (Reverse Polish Notation), Evaluate RPN Expression
  9.  *
  10.  * Example:
  11.  *
  12.  *     $expression = "(2^3)+sin(30)-(!4)+(3/4)";
  13.  *
  14.  *     $rpn = new Math_Rpn();
  15.  *     echo $rpn->calculate($expression,'deg',false);
  16.  *
  17.  *
  18.  * @author   Maciej Szczytowski <admin@e-rower.pl>
  19.  * @version  1.1
  20.  * @package  math
  21.  * @access   public
  22.  */
  23.  
  24. require_once 'PEAR.php';
  25.  
  26. class Math_Rpn
  27. {
  28.     /**
  29.      * Input expression
  30.      *
  31.      * @var    string
  32.      * @access private
  33.      */
  34.     var $_input = '';
  35.  
  36.     /**
  37.      * Array with input expression
  38.      *
  39.      * @var    array
  40.      * @access private
  41.      */
  42.     var $_input_array = array();
  43.  
  44.     /**
  45.      * Array with output expression in RPN
  46.      *
  47.      * @var    array
  48.      * @access private
  49.      */
  50.     var $_output = array();
  51.  
  52.     /**
  53.      * Temporary stack
  54.      *
  55.      * @var    array
  56.      * @access private
  57.      */
  58.     var $_stack = array();
  59.  
  60.     /**
  61.      * Value of expression
  62.      *
  63.      * @var    float
  64.      * @access private
  65.      */
  66.     var $_value = 0.0;
  67.  
  68.     /**
  69.      * Angle's unit: rad - true, deg - false
  70.      *
  71.      * @var    boolean
  72.      * @access private
  73.      */
  74.     var $_angle = true;
  75.  
  76.     /**
  77.      * PEAR Error
  78.      *
  79.      * @var    object PEAR
  80.      * @access private
  81.      */
  82.     var $_error = null;
  83.  
  84.     /**
  85.      * Timer
  86.      *
  87.      * @var    float
  88.      * @access private
  89.      */
  90.     var $_timer = 0.0;
  91.  
  92.     /**
  93.      * Array of operators whit priority and math function
  94.      * operator => (name, priority, number of arguments, function)
  95.      *
  96.      * @var    array
  97.      * @access private
  98.      */
  99.     var $_operation = array (
  100.         '('    => array ('left bracket', 0),
  101.         ')'    => array ('right bracket', 1),
  102.         '+'    => array ('sum', 1, 2, '_sum'),
  103.         '-'    => array ('difference', 1, 2, '_difference'),
  104.         '*'    => array ('multiplication', 2, 2, '_multiplication'),
  105.         '/'    => array ('division', 2, 2, '_division'),
  106.         'r'    => array ('root', 3, 2, '_root'),
  107.         '^'    => array ('power', 3, 2, '_power'),
  108.         'sin'  => array ('sine', 3, 1, '_sin'),
  109.         'cos'  => array ('cosine', 3, 1, '_cos'),
  110.         'tan'  => array ('tangent', 3, 1, '_tan'),
  111.         'asin' => array ('asine', 3, 1, '_asin'),
  112.         'acos' => array ('acosine', 3, 1, '_acos'),
  113.         'atan' => array ('atangent', 3, 1, '_atan'),
  114.         'sqrt' => array ('square root', 3, 1, '_sqrt'),
  115.         'exp'    => array ('power of e', 3, 1, '_exp'),
  116.         'log'  => array ('logarithm', 3, 1, '_log'),
  117.         'ln'   => array ('natural logarithm', 3, 1, '_ln'),
  118.         'E'  => array ('power of 10', 3, 1, '_E'),
  119.         'abs'  => array ('absolute value', 3, 1, '_abs'),
  120.         '!'    => array ('factorial', 3, 1, '_factorial'),
  121.         'pi'   => array ('value of pi', 4, 0, '_const_pi'),
  122.         'e'    => array ('value of e', 4, 0, '_const_e'),
  123.         'mod'    => array ('modulo', 3, 2, '_mod'),
  124.         'div'    => array ('integer division', 3, 2, '_div'),
  125.     );
  126.  
  127.     /**
  128.      * Return a PEAR error
  129.      *
  130.      * @return object PEAR error
  131.      * @access private
  132.      */
  133.     function _raiseError ($error) {
  134.         return PEAR::raiseError($error);
  135.     }
  136.  
  137.     /**
  138.      * Return a operator's array
  139.      *
  140.      * @return array Array with operator's name, priority, arguments, function's name and syntax
  141.      * @access public
  142.      */
  143.     function getOperators () {
  144.         $return = array();
  145.         while(list($key, $val) = each($this->_operation)) {
  146.  
  147.             if (array_key_exists (2, $val) && $val[2] == 2) {
  148.                 $syntax = 'A ' . $key . ' B';
  149.                 $arguments = 2;
  150.             } elseif (array_key_exists (2, $val) && $val[2] == 1) {
  151.                 $syntax = $key . ' A';
  152.                 $arguments = 1;
  153.             } else {
  154.                 $syntax = $key;
  155.                 $arguments = 0;
  156.             }
  157.  
  158.             if(array_key_exists (3, $val)) $function = $val[3]; else $function = '';
  159.  
  160.             $return[] = array (
  161.                 'operator' => $key,
  162.                 'name' => $val[0],
  163.                 'priority' => $val[1],
  164.                 'arguments' => $arguments,
  165.                 'function' => $function,
  166.                 'syntax' => $syntax
  167.             );
  168.         }
  169.  
  170.         return $return;
  171.     }
  172.  
  173.     /**
  174.      * Add new operator
  175.      *
  176.      * @param string $operator New operator
  177.      * @param string $function Function name
  178.      * @param integer $priority New operator's priority
  179.      * @param integer $no_of_arg Number of function's arguments
  180.      * @param string $text New operator's description
  181.      * @access public
  182.      */
  183.     function addOperator ($operator, $function_name, $priority = 3, $no_of_arg = 0, $text = '') {
  184.         if(preg_match("/^([\W\w]+)\:\:([\W\w]+)$/",$function_name,$match)) {
  185.             $class = $match[1];
  186.             $method = $match[2];
  187.             $function = array (
  188.                'type' => 'userMethod',
  189.                'class' => $class,
  190.                'method' => $method
  191.             );
  192.         } else {
  193.             $function = array (
  194.                'type' => 'userFunction',
  195.                'function' => $function_name
  196.             );
  197.         }
  198.  
  199.         $this->_operation[$operator] = array ($text, $priority, $no_of_arg, $function);
  200.     }
  201.  
  202.     /**
  203.      * Calculate the $input expression
  204.      *
  205.      * @param mixed $input Infix expression string or RPN expression string
  206.      * @param string $angle Angle's unit - 'rad' or 'deg'
  207.      * @param boolean $is_rpn True if $input is RPN expression or false if $input is infix expression
  208.      * @return mixed Value of $input expression or a PEAR error
  209.      * @access public
  210.      */
  211.     function calculate($input = '', $angle = 'rad', $is_rpn = true) {
  212.  
  213.         $this->_angle = (boolean) ($angle == 'rad');
  214.  
  215.         if($input == '') {
  216.             $this->_error = $this->_raiseError('Empty input expression');
  217.             return $this->_error;
  218.         }
  219.  
  220.         if(!$is_rpn) {
  221.             $this->_input = $input;
  222.  
  223.             $this->_stringToArray ();
  224.             if($this->_error <> null) return $this->_error;
  225.  
  226.             $this->_arrayToRpn();
  227.             if($this->_error <> null) return $this->_error;
  228.         } else {
  229.             if (is_array($input)) {
  230.                 $input = implode(' ', $input);
  231.             }
  232.  
  233.             $this->_input = $input;
  234.             $this->_input_array = explode(' ',$input);
  235.             $this->_output = explode(' ',$input);
  236.         }
  237.  
  238.         $this->_rpnToValue();
  239.         if($this->_error <> null) return $this->_error;
  240.  
  241.         return $this->_value;
  242.     }
  243.  
  244.     /**
  245.      * Calculate the $input expression (alias of calculate())
  246.      *
  247.      * @param mixed $input Infix expression string or RPN expression array
  248.      * @param string $angle Angle's unit - 'rad' or 'deg'
  249.      * @param boolean $is_rpn True if $input is RPN expression or false if $input is infix expression
  250.      * @return mixed Value of $input expression or a PEAR error
  251.      * @access public
  252.      */
  253.     function evaluate($input = '', $angle = 'rad', $is_rpn = false) {
  254.         return $this-> calculate($input, $angle, $is_rpn);
  255.     }
  256.  
  257.     /**
  258.      * Return a input array
  259.      *
  260.      * @return array Input array
  261.      * @access public
  262.      */
  263.     function getInputArray() {
  264.         return $this->_input_array;
  265.     }
  266.  
  267.     /**
  268.      * Return a RPN array
  269.      *
  270.      * @return array RPN array
  271.      * @access public
  272.      */
  273.     function getRpnArray() {
  274.         return $this->_output;
  275.     }
  276.  
  277.     /**
  278.      * Return a counting time in second
  279.      *
  280.      * @return float Counting time in seconds
  281.      * @access public
  282.      */
  283.     function getTimer() {
  284.         return $this->_timer;
  285.     }
  286.  
  287.     /**
  288.      * Check that $key is a key of $array (conformity to php<4.1.0)
  289.      *
  290.      * @param string $key
  291.      * @param array $array
  292.      * @param integer $type 0 - return true if $key is $array's key, 1 - return true if $key is $array's key and there isn't any occurrence of $key in another $array's key
  293.      * @return boolean true when $key is a key of $array, or false
  294.      * @access private
  295.      */
  296.  
  297.     function _keyExists($key,$array,$type) {
  298.         $keys = array_keys($array);
  299.  
  300.         if($type == 1) {
  301.             $count = 0;
  302.             while (list($keys_key, $keys_val) = each($keys)) {
  303.                 if(is_integer(strpos($keys_val, $key)) && (strpos($keys_val, $key)==0)) $count++;
  304.             }
  305.             if(($count==1) && in_array($key,$keys)) return true;
  306.             else return false;
  307.         } else {
  308.             if(in_array($key,$keys)) return true;
  309.             else return false;
  310.         }
  311.     }
  312.  
  313.     /**
  314.      * Check that $value is nan (conformity to php<4.2.0)
  315.      *
  316.      * @param float $value checking value
  317.      * @return boolean true when $value is nan, or false
  318.      * @access private
  319.      */
  320.     function _isNan($value) {
  321.         if(function_exists('is_nan')) {
  322.             return is_nan($value);
  323.         } else {
  324.             if((substr($value,-3) == 'IND') || (substr($value,-3) == 'NAN')) return true;
  325.             else return false;
  326.         }
  327.     }
  328.  
  329.     /**
  330.      * Check that $value is infinite (conformity to php<4.2.0)
  331.      *
  332.      * @param float $value checking value
  333.      * @return boolean true when $value is infinite, or false
  334.      * @access private
  335.      */
  336.     function _isInfinite($value) {
  337.         if(function_exists('is_finite')) {
  338.             return !is_finite($value);
  339.         } else {
  340.             if(substr($value,-3) == 'INF') return true;
  341.             else return false;
  342.         }
  343.     }
  344.  
  345.     /**
  346.      * Change input expression into array
  347.      *
  348.      * @return array Input expression changed into array
  349.      * @access private
  350.      */
  351.     function _stringToArray () {
  352.         $temp_operator = null;
  353.         $temp_value = null;
  354.  
  355.         $this->_input = str_replace(" ","",$this->_input);
  356.  
  357.         for($i = 0; $i < strlen($this->_input); $i++) {
  358.             if ($this->_input[$i] == ' ') {
  359.                 if ($temp_operator != null) {
  360.                     array_push($this->_input_array, $temp_operator);
  361.                     $temp_operator = null;
  362.                 }
  363.                 if ($temp_value != null) {
  364.                     array_push($this->_input_array, $temp_value);
  365.                     $temp_value = null;
  366.                 }
  367.             } elseif (($temp_value == null) && (!array_key_exists($temp_operator,$this->_operation) || !array_key_exists(2,$this->_operation[$temp_operator]) || $this->_operation[$temp_operator][2]>0) && ($this->_input[$i] == '-')) {
  368.                 if ($temp_operator != null) {
  369.                     array_push($this->_input_array, $temp_operator);
  370.                     $temp_operator = null;
  371.                 }
  372.  
  373.                 array_push($this->_input_array, '-1');
  374.                 array_push($this->_input_array, '*');
  375.             } elseif ((is_numeric($this->_input[$i])) || ($this->_input[$i] == '.')) {
  376.                 if ($temp_operator != null) {
  377.                     array_push($this->_input_array, $temp_operator);
  378.                     $temp_operator = null;
  379.                 }
  380.  
  381.                 $temp_value .= $this->_input[$i];
  382.             } else {
  383.                 if ($this->_keyExists($temp_operator, $this->_operation, 1)) {
  384.                     array_push($this->_input_array, $temp_operator);
  385.                     $temp_operator = null;
  386.                 }
  387.  
  388.                 if ($temp_value != null) {
  389.                     array_push($this->_input_array, $temp_value);
  390.                     $temp_value = null;
  391.                 }
  392.  
  393.                 $temp_operator .= $this->_input[$i];
  394.             }
  395.         }
  396.  
  397.         if ($temp_operator != null && $temp_operator != ' ') {
  398.             array_push($this->_input_array, $temp_operator);
  399.         } elseif($temp_value != null && $temp_value != ' ') {
  400.             array_push($this->_input_array, $temp_value);
  401.         }
  402.  
  403.         $this->_testInput();
  404.  
  405.         return $this->_input_array;
  406.     }
  407.  
  408.     /**
  409.      * Check input array and return correct array or a PEAR Error
  410.      *
  411.      * @return object Null or a PEAR Error
  412.      * @access private
  413.      */
  414.     function _testInput() {
  415.         if (!count($this->_input_array)) {
  416.             $this->_input_array = null;
  417.             $this->_error = $this->_raiseError('Undefined input array');
  418.             return $this->_error;
  419.         }
  420.  
  421.         $bracket = 0;
  422.         for($i = 0; $i < count($this->_input_array); $i++) if ($this->_input_array[$i] == '(') $bracket++;
  423.         for($i = 0; $i < count($this->_input_array); $i++) if ($this->_input_array[$i] == ')') $bracket--;
  424.  
  425.         if ($bracket <> 0) {
  426.                 $this->_input_array = null;
  427.                 $this->_error = $this->_raiseError('Syntax error');
  428.                 return $this->_error;
  429.         }
  430.  
  431.         for($i = 0; $i < count($this->_input_array); $i++) {
  432.             if ((!is_numeric($this->_input_array[$i])) && (!$this->_keyExists($this->_input_array[$i], $this->_operation, 0))) {
  433.                 $error_operator = $this->_input_array[$i];
  434.                 $this->_input_array = null;
  435.                 $this->_error = $this->_raiseError('Undefined operator \''. $error_operator.'\'');
  436.                 return $this->_error;
  437.             }
  438.         }
  439.  
  440.         $this->_error = null;
  441.         return $this->_error;
  442.     }
  443.  
  444.     /**
  445.      * Add value to the end of stack
  446.      *
  447.      * @param string $value Value to add into stack
  448.      * @access private
  449.      */
  450.     function _stackAdd($value) {
  451.         array_push($this->_stack, $value);
  452.     }
  453.  
  454.     /**
  455.      * Delete and return value from the end of stack
  456.      *
  457.      * @return string Value deleted from stack
  458.      * @access private
  459.      */
  460.     function _stackDelete() {
  461.         return array_pop($this->_stack);
  462.     }
  463.  
  464.     /**
  465.      * Return priority of value
  466.      *
  467.      * @param string $value Value to get priority
  468.      * @return integer Priority
  469.      * @access private
  470.      */
  471.     function _priority($value) {
  472.         return $this->_operation[$value][1];
  473.     }
  474.     /**
  475.      * Return priority of value from the end of stack
  476.      *
  477.      * @return integer Priority of operator from stack's top
  478.      * @access private
  479.      */
  480.     function _stackPriority() {
  481.         $value = $this->_stackDelete();
  482.         $this->_stackAdd($value);
  483.         return $this->_priority($value);
  484.     }
  485.  
  486.     /**
  487.      * Return true whene the stack is empty
  488.      *
  489.      * @return boolean Stack is empty (true) or not (false)
  490.      * @access private
  491.      */
  492.     function _stackEmpty() {
  493.         if (count($this->_stack)) {
  494.             return false;
  495.         }
  496.         else return true;
  497.     }
  498.  
  499.     /**
  500.      * Add value into output array
  501.      *
  502.      * @param string $value Value to add into output array
  503.      * @access private
  504.      */
  505.     function _outputAdd($value) {
  506.         if ($value<>'(') {
  507.             array_push($this->_output, $value);
  508.         }
  509.     }
  510.  
  511.     /**
  512.      * Change input array into RPN array
  513.      *
  514.      * @return array Array with RPN expression
  515.      * @access private
  516.      */
  517.     function _arrayToRpn() {
  518.  
  519.         if ($this->_error <> null) {
  520.             $this->_output = array();
  521.             return $this->_output;
  522.         }
  523.  
  524.         for($i = 0; $i < count($this->_input_array); $i++) {
  525.  
  526.             $temp = $this->_input_array[$i];
  527.  
  528.             if (is_numeric($temp)) {
  529.                 $this->_outputAdd($temp);
  530.             } else {
  531.                 if ($temp == ')') {
  532.                     while(!$this->_stackEmpty() && ($this->_stackPriority() >= 1)) {
  533.                         $this->_outputAdd($this->_stackDelete());
  534.                     }
  535.                     if (!$this->_stackEmpty()) {
  536.                         $this->_stackDelete();
  537.                     }
  538.  
  539.                 } elseif ($temp=='(') {
  540.                     $this->_stackAdd($temp);
  541.                 } elseif (($this->_stackEmpty()) || (($this->_priority($temp) > $this->_stackPriority()))) {
  542.                    $this-> _stackAdd($temp);
  543.                 } else {
  544.                     while(!$this->_stackEmpty() && ($this->_priority($temp) <= $this->_stackPriority())) {
  545.                         $this->_outputAdd($this->_stackDelete());
  546.                     }
  547.                     $this->_stackAdd($temp);
  548.                 }
  549.  
  550.             }
  551.  
  552.         }
  553.  
  554.         while(!$this->_stackEmpty()) {
  555.             $this->_outputAdd($this->_stackDelete());
  556.         }
  557.  
  558.         return $this->_output;
  559.     }
  560.  
  561.     /**
  562.      * Return position of the first operator in array
  563.      *
  564.      * @param array $array Temporary array
  565.      * @return integer Position of the first operator
  566.      * @access private
  567.      */
  568.     function _nextOperator($array) {
  569.         $pos = 0;
  570.         while(is_numeric($array[$pos])) {
  571.             $pos++;
  572.             if ($pos >= count($array)) {
  573.                 return -1;
  574.             }
  575.         }
  576.         return $pos;
  577.  
  578.     }
  579.  
  580.     /**
  581.      * Delete from array operator [posision $pos] and its argument and insert new value
  582.      *
  583.      * @param array $temp Temporary array
  584.      * @param integer $pos Position of the last operator
  585.      * @param integer $arg Number of last operator's arguments
  586.      * @param float $result Last operation result
  587.      * @return array New temporary array
  588.      * @access private
  589.      */
  590.     function _refresh($temp, $pos, $arg, $result) {
  591.         $temp1 = array_slice($temp, 0, $pos-$arg);
  592.         $temp1[] = $result;
  593.         $temp2 = array_slice($temp, $pos+1);
  594.         return array_merge($temp1, $temp2);
  595.     }
  596.  
  597.     /**
  598.      * Math function
  599.      *
  600.      * @param array $temp Temporary array
  601.      * @param integer $pos Position of operator
  602.      * @return float Function's relult
  603.      * @access private
  604.      */
  605.     function _sum($temp, $pos) {
  606.         return $temp[$pos-2]+$temp[$pos-1];
  607.     }
  608.  
  609.     /**
  610.      * Math function
  611.      *
  612.      * @param array $temp Temporary array
  613.      * @param integer $pos Position of operator
  614.      * @return float Function's relult
  615.      * @access private
  616.      */
  617.     function _difference($temp, $pos) {
  618.         return $temp[$pos-2]-$temp[$pos-1];
  619.     }
  620.  
  621.     /**
  622.      * Math function
  623.      *
  624.      * @param array $temp Temporary array
  625.      * @param integer $pos Position of operator
  626.      * @return float Function's relult
  627.      * @access private
  628.      */
  629.     function _multiplication($temp, $pos) {
  630.         return $temp[$pos-2]*$temp[$pos-1];
  631.     }
  632.  
  633.     /**
  634.      * Math function
  635.      *
  636.      * @param array $temp Temporary array
  637.      * @param integer $pos Position of operator
  638.      * @return float Function's relult
  639.      * @access private
  640.      */
  641.     function _division($temp, $pos) {
  642.         if ($temp[$pos-1]==0) {
  643.             $this->_error = $this->_raiseError('Division by 0');
  644.             $this->_value = null;
  645.             return $this->_value;
  646.         }
  647.         return $temp[$pos-2]/$temp[$pos-1];
  648.     }
  649.  
  650.     /**
  651.      * Math function
  652.      *
  653.      * @param array $temp Temporary array
  654.      * @param integer $pos Position of operator
  655.      * @return float Function's relult
  656.      * @access private
  657.      */
  658.     function _root($temp, $pos) {
  659.         return pow($temp[$pos-1], (1/$temp[$pos-2]));
  660.     }
  661.  
  662.     /**
  663.      * Math function
  664.      *
  665.      * @param array $temp Temporary array
  666.      * @param integer $pos Position of operator
  667.      * @return float Function's relult
  668.      * @access private
  669.      */
  670.     function _power($temp, $pos) {
  671.         return pow($temp[$pos-2], $temp[$pos-1]);
  672.     }
  673.  
  674.     /**
  675.      * Math function
  676.      *
  677.      * @param array $temp Temporary array
  678.      * @param integer $pos Position of operator
  679.      * @return float Function's relult
  680.      * @access private
  681.      */
  682.     function _sin($temp, $pos) {
  683.         if ($this->_angle) {
  684.             $angle = $temp[$pos-1];
  685.         } else {
  686.             $angle = deg2rad($temp[$pos-1]);
  687.         }
  688.         return sin($angle);
  689.     }
  690.  
  691.     /**
  692.      * Math function
  693.      *
  694.      * @param array $temp Temporary array
  695.      * @param integer $pos Position of operator
  696.      * @return float Function's relult
  697.      * @access private
  698.      */
  699.     function _cos($temp, $pos) {
  700.         if ($this->_angle) {
  701.             $angle = $temp[$pos-1];
  702.         } else {
  703.             $angle = deg2rad($temp[$pos-1]);
  704.         }
  705.         return cos($angle);
  706.     }
  707.  
  708.     /**
  709.      * Math function
  710.      *
  711.      * @param array $temp Temporary array
  712.      * @param integer $pos Position of operator
  713.      * @return float Function's relult
  714.      * @access private
  715.      */
  716.     function _tan($temp, $pos) {
  717.         if ($this->_angle) {
  718.             $angle = $temp[$pos-1];
  719.         } else {
  720.             $angle = deg2rad($temp[$pos-1]);
  721.         }
  722.         return tan($angle);
  723.     }
  724.  
  725.     /**
  726.      * Math function
  727.      *
  728.      * @param array $temp Temporary array
  729.      * @param integer $pos Position of operator
  730.      * @return float Function's relult
  731.      * @access private
  732.      */
  733.     function _asin($temp, $pos) {
  734.         $angle = asin($temp[$pos-1]);
  735.         if (!$this->_angle) {
  736.             $angle = rad2deg($angle);
  737.         }
  738.         return $angle;
  739.     }
  740.  
  741.     /**
  742.      * Math function
  743.      *
  744.      * @param array $temp Temporary array
  745.      * @param integer $pos Position of operator
  746.      * @return float Function's relult
  747.      * @access private
  748.      */
  749.     function _acos($temp, $pos) {
  750.         $angle = acos($temp[$pos-1]);
  751.         if (!$this->_angle) {
  752.             $angle = rad2deg($angle);
  753.         }
  754.         return $angle;
  755.     }
  756.  
  757.     /**
  758.      * Math function
  759.      *
  760.      * @param array $temp Temporary array
  761.      * @param integer $pos Position of operator
  762.      * @return float Function's relult
  763.      * @access private
  764.      */
  765.     function _atan($temp, $pos) {
  766.         $angle = atan($temp[$pos-1]);
  767.         if (!$this->_angle) {
  768.             $angle = rad2deg($angle);
  769.         }
  770.         return $angle;
  771.     }
  772.  
  773.     /**
  774.      * Math function
  775.      *
  776.      * @param array $temp Temporary array
  777.      * @param integer $pos Position of operator
  778.      * @return float Function's relult
  779.      * @access private
  780.      */
  781.     function _sqrt($temp, $pos) {
  782.         return sqrt($temp[$pos-1]);
  783.     }
  784.  
  785.     /**
  786.      * Math function
  787.      *
  788.      * @param array $temp Temporary array
  789.      * @param integer $pos Position of operator
  790.      * @return float Function's relult
  791.      * @access private
  792.      */
  793.     function _exp($temp, $pos) {
  794.         return exp($temp[$pos-1]);
  795.     }
  796.  
  797.     /**
  798.      * Math function
  799.      *
  800.      * @param array $temp Temporary array
  801.      * @param integer $pos Position of operator
  802.      * @return float Function's relult
  803.      * @access private
  804.      */
  805.     function _log($temp, $pos) {
  806.         return log10($temp[$pos-1]);
  807.     }
  808.  
  809.     /**
  810.      * Math function
  811.      *
  812.      * @param array $temp Temporary array
  813.      * @param integer $pos Position of operator
  814.      * @return float Function's relult
  815.      * @access private
  816.      */
  817.     function _ln($temp, $pos) {
  818.         return log($temp[$pos-1]);
  819.     }
  820.  
  821.     /**
  822.      * Math function
  823.      *
  824.      * @param array $temp Temporary array
  825.      * @param integer $pos Position of operator
  826.      * @return float Function's relult
  827.      * @access private
  828.      */
  829.     function _const_pi($temp, $pos) {
  830.         return M_PI;
  831.     }
  832.  
  833.     /**
  834.      * Math function
  835.      *
  836.      * @param array $temp Temporary array
  837.      * @param integer $pos Position of operator
  838.      * @return float Function's relult
  839.      * @access private
  840.      */
  841.     function _const_e($temp, $pos) {
  842.         return M_E;
  843.     }
  844.  
  845.     /**
  846.      * Math function
  847.      *
  848.      * @param array $temp Temporary array
  849.      * @param integer $pos Position of operator
  850.      * @return float Function's relult
  851.      * @access private
  852.      */
  853.     function _E($temp, $pos) {
  854.         return pow(10, $temp[$pos-1]);
  855.     }
  856.  
  857.     /**
  858.      * Math function
  859.      *
  860.      * @param array $temp Temporary array
  861.      * @param integer $pos Position of operator
  862.      * @return float Function's relult
  863.      * @access private
  864.      */
  865.     function _factorial($temp, $pos) {
  866.         $factorial = 1;
  867.         for($i=1;$i<=$temp[$pos-1];$i++) {
  868.             $factorial *= $i;
  869.         }
  870.         return $factorial;
  871.     }
  872.  
  873.     /**
  874.      * Math function
  875.      *
  876.      * @param array $temp Temporary array
  877.      * @param integer $pos Position of operator
  878.      * @return float Function's relult
  879.      * @access private
  880.      */
  881.     function _abs($temp, $pos) {
  882.         return abs($temp[$pos-1]);
  883.     }
  884.  
  885.     /**
  886.      * Math function
  887.      *
  888.      * @param array $temp Temporary array
  889.      * @param integer $pos Position of operator
  890.      * @return float Function's relult
  891.      * @access private
  892.      */
  893.     function _mod($temp, $pos) {
  894.         return $temp[$pos-2]%$temp[$pos-1];
  895.     }
  896.  
  897.     /**
  898.      * Math function
  899.      *
  900.      * @param array $temp Temporary array
  901.      * @param integer $pos Position of operator
  902.      * @return float Function's relult
  903.      * @access private
  904.      */
  905.     function _div($temp, $pos) {
  906.         return floor($temp[$pos-2]/$temp[$pos-1]);
  907.     }
  908.  
  909.     /**
  910.      * Calculate RPN Expression and return value
  911.      *
  912.      * @return float Result of input expression
  913.      * @access private
  914.      */
  915.     function _rpnToValue() {
  916.  
  917.         $time1 = $this->_getMicroTime();
  918.  
  919.         if ($this->_error <> null) {
  920.             $this->_value = null;
  921.             return $this->_value;
  922.         }
  923.  
  924.         $this->_value = 0;
  925.         $temp = $this->_output;
  926.  
  927.         do {
  928.             $pos = $this->_nextOperator($temp);
  929.  
  930.             if ($pos == -1) {
  931.                 $this->_error = $this->_raiseError('Syntax error');
  932.                 $this->_value = null;
  933.                 return $this->_value;
  934.             }
  935.  
  936.             $operator = $this->_operation[$temp[$pos]];
  937.             $arg = $operator[2];
  938.             $function = $operator[3];
  939.  
  940.             if (($arg==2) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]) || !isset($temp[$pos-2]) || !is_numeric($temp[$pos-2]))) {
  941.                 $this->_error = $this->_raiseError('Syntax error');
  942.                 $this->_value = null;
  943.                 return $this->_value;
  944.             } elseif (($arg==1) && (!isset($temp[$pos-1]) || !is_numeric($temp[$pos-1]))) {
  945.                 $this->_error = $this->_raiseError('Syntax error');
  946.                 $this->_value = null;
  947.                 return $this->_value;
  948.             }
  949.  
  950.             if(is_array($function)) {
  951.  
  952.                 if($arg==2) $arg_array = array($temp[$pos-2],$temp[$pos-1]);
  953.                 elseif($arg==1) $arg_array = array($temp[$pos-1]);
  954.                 else $arg_array = array();
  955.  
  956.                 if($function['type'] == 'userFunction') {
  957.                     $this->_value = call_user_func_array($function['function'], $arg_array);
  958.                 } else {
  959.                     $function_array = array(&$function['class'], $function['method']);
  960.                     $this->_value = call_user_func_array($function_array, $arg_array);
  961.                 }
  962.             } else {
  963.                 $this->_value = $this->$function($temp, $pos);
  964.             }
  965.  
  966.             if ($this->_isNan($this->_value)) {
  967.                 $this->_error = $this->_raiseError('NAN value');
  968.                 $this->_value = null;
  969.                 return $this->_value;
  970.             } elseif ($this->_isInfinite($this->_value)) {
  971.                 $this->_error = $this->_raiseError('Infinite value');
  972.                 $this->_value = null;
  973.                 return $this->_value;
  974.             } elseif (is_null($this->_value)) {
  975.                 return $this->_value;
  976.             }
  977.  
  978.             $temp = $this->_refresh($temp, $pos, $arg, $this->_value);
  979.         } while(count($temp) > 1);
  980.  
  981.         $this->_value = $temp[0];
  982.  
  983.         $time2 = $this->_getMicroTime();
  984.  
  985.         $this->_timer = $time2 - $time1;
  986.  
  987.         return $this->_value;
  988.     }
  989.  
  990.     /**
  991.      * Return a time in second
  992.      *
  993.      * @return float Current time in seconds
  994.      * @access private
  995.      */
  996.     function _getMicroTime() {
  997.         list($usec, $sec) = explode(" ", microtime());
  998.         return ((float)$usec + (float)$sec);
  999.     }
  1000.  
  1001. }
  1002.  
  1003. ?>